#include "gui.h"
#include <uview.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <dotfont.h>

static int __gui_init_done = 0;
static int __gui_main_loop = 0;

int __gui_has_window_close = 0;

int gui_check_main_loop()
{
    return __gui_main_loop;
}

int gui_init(int *argc, int **argv[])
{
    gui_text_init();
    gui_view_init();

    __gui_main_loop = 1;
    __gui_has_window_close = 0;
    __gui_init_done = 1;
    return 0;
}

void gui_exit()
{
    if (__gui_init_done)
    {
        gui_view_t *pview, *pnext;
        gui_view_traversal_safe(pview, pnext)
        {
            assert(pview->spirit);
            gui_window_quit(pview->spirit);
        }
    }

    gui_view_exit();
    __gui_init_done = 0;
}

//#define DEBUG_GUI

int gui_main()
{
    if (!__gui_init_done)
    {
        perror("gui init no called before gui main");
        abort();
    }
    gui_spirit_t *spirit;
    gui_window_t *window;
    uview_msg_t msg;
    gui_view_t *pview, *pnext;
    int filter_val;
    int target;
    int view_num = gui_view_length();
    dprintf("[gui main] view num %d\n",view_num);

    while (__gui_main_loop && view_num > 0)
    {
        view_num = gui_view_length();
        gui_view_traversal_safe(pview, pnext)
        {
            if (view_num >= 2) // have two and more view
            {
                if (!pview->nowait)
                {
                    pview->nowait = 1;
                    uview_set_nowait(pview->view, pview->nowait);
                }
            }
            else
            {
                if (pview->nowait) // only have one view,set to block
                {
                    pview->nowait = 0;
                    uview_set_nowait(pview->view, pview->nowait);
                }
            }

            if(uview_get_msg(pview->view,&msg)<0)
                continue;


            #ifdef DEBUG_GUI
            dprintf("msg id %d targe %d data0 %d data1 %d data2 %d data3 %d\n",msg.id,msg.targe,msg.data0,msg.data1,msg.data2,msg.data3);
            #endif 
            
            __gui_has_window_close=0; //no window close
            filter_val=1; //msg no filter
            target=uview_msg_get_targe(&msg);
            window=GUI_WINDOW(pview->spirit);
            if(pview->real_view==target) //target is current view
            {
                list_traversal_all_owner_to_next(spirit,&pview->spirit_list_head,list)
                {
                    if(!(filter_val=gui_window_main(spirit,&msg)))
                        break;
                    if(!__gui_main_loop)
                    return 0;
                    if(__gui_has_window_close)
                        break;
                }
                //check if had window closed 
                if(!__gui_main_loop)
                    return 0;
                if(__gui_has_window_close)
                    continue;
                if(filter_val)
                    filter_val=gui_window_filter_msg(window,&spirit);
            }
            //called user filter function
            if(filter_val)
            {
                if(window->routine)
                    window->routine(&window->spirit,&msg);
            }
        }
    }
    return 0;
}


int gui_poll()
{
    if(!__gui_init_done)
    {
        perror("gui init no called");
        abort();
    }
    gui_spirit_t *spirit;
    gui_window_t *window;
    gui_view_t *pview,*pnext;
    uview_msg_t msg;
    int filter_val;
    int target;
    int view_num=gui_view_length();

    if(__gui_main_loop&&view_num>0)
    {
        gui_view_traversal_safe(pview,pnext)
        {
            if(!pview->nowait)
            {
                pview->nowait=1; 
                uview_set_nowait(pview->view,pview->nowait);
            }

            while(!uview_get_msg(pview->view,&msg))
            {
                #ifdef DEBUG_GUI
                dprintf("[gui] msg id %d data %d %d %d %d\n",msg.id,msg.data0,msg.data1,msg.data2,msg.data3,msg.data3);
                #endif
                __gui_has_window_close=0;
                filter_val=1;
                target=uview_msg_get_targe(&msg);
                window=GUI_WINDOW(pview->spirit);
                if(pview->real_view==target) //target is current view
                {
                    list_traversal_all_owner_to_next(spirit,&pview->spirit_list_head,list)
                    {
                        if(!(filter_val=gui_window_main(spirit,&msg)))
                            break;
                        if(!__gui_main_loop)
                            return 0;
                        if(__gui_has_window_close)
                            break;   
                    }

                    if(!__gui_main_loop)
                        return 0;
                    if(__gui_has_window_close)
                        continue;
                    if(filter_val)
                        gui_window_filter_msg(window,&msg);
                }  
                if(filter_val)
                {
                    if(window->routine)
                        window->routine(&window->spirit,&msg);
                }
            }
        }   
    }
    else 
    {
        return 0; //gui stop running 
    }
    return 1;
}

int gui_main_quit()
{
    __gui_main_loop=0;
    return 0;
}
